package com.insigma.business.qrcode.soldier.util;

import cn.hutool.core.bean.BeanUtil;
import com.insigma.business.qrcode.common.annotation.MybatisCryptAspect;
import com.insigma.business.qrcode.common.dao.CommonFeedbackDao;
import com.insigma.business.qrcode.soldier.dto.SystemConfigService;
import com.insigma.business.qrcode.soldier.entity.SystemConfigDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;


@Slf4j
@Service
public class PrivacyEncComponent {

    @Autowired
    private MybatisCryptAspect mybatisCryptAspect;

    @Autowired
    private SystemConfigService systemConfigService;
    
    public static void encodeField(List list, String idCardNoField, String mobileField, String addressField) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (Object o : list) {
            encode(o, idCardNoField, mobileField, addressField);
        }
    }

    private static void encode(Object o, String idCardNoField, String mobileField, String addressField) {
        if (Strings.isNotBlank(idCardNoField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, idCardNoField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, idCardNoField, PrivacyEncUtils.encodeIdCardNo(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(mobileField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, mobileField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, mobileField, PrivacyEncUtils.encodeMobile(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(addressField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, addressField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, addressField, PrivacyEncUtils.encodeCommonChinese(fieldValue.toString()));
            }
        }
    }

    
    public static void encodeField(Object o, String idCardNoField, String mobileField, String addressField) {
        if (o == null) {
            return;
        }

        if (o instanceof List) {
            decodeField((List)o, idCardNoField, mobileField,addressField);
            return;
        }
        encode(o, idCardNoField, mobileField, addressField);
    }
    
    public static void encodeSearchField(Object o, String idCardNoField, String mobileField, String addressField) {
        if (o == null) {
            return;
        }

        if (Strings.isNotBlank(idCardNoField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, idCardNoField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, idCardNoField, PrivacyEncUtils.encodeCharByIdCardNo(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(mobileField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, mobileField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, mobileField, PrivacyEncUtils.encodeMobile(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(addressField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, addressField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, addressField, PrivacyEncUtils.encodeCommonChinese(fieldValue.toString()));
            }
        }
    }

    
    public static void decodeField(List list, String idCardNoField, String mobileField, String addressField) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (Object o : list) {
            decode(o, idCardNoField, mobileField, addressField);
        }
    }

    
    public static void decodeField(Object o, String idCardNoField, String mobileField, String addressField) {
        if (o == null) {
            return;
        }

        if (o instanceof List) {
            decodeField((List)o, idCardNoField, mobileField,addressField);
            return;
        }
        decode(o, idCardNoField, mobileField, addressField);
    }

    private static void decode(Object o, String idCardNoField, String mobileField, String addressField) {
        if (Strings.isNotBlank(idCardNoField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, idCardNoField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, idCardNoField, PrivacyEncUtils.decodeIdCardNo(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(mobileField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, mobileField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, mobileField, PrivacyEncUtils.decodeMobile(fieldValue.toString()));
            }
        }

        if (Strings.isNotBlank(addressField)) {
            Object fieldValue = BeanUtil.getFieldValue(o, addressField);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, addressField, PrivacyEncUtils.decodeCommonChinese(fieldValue.toString()));
            }
        }
    }

    private static void setValueIfFieldNotBlank(String field, Object o) {
        if (Strings.isNotBlank(field)) {
            Object fieldValue = BeanUtil.getFieldValue(o, field);
            if (fieldValue != null) {
                BeanUtil.setFieldValue(o, field, PrivacyEncUtils.decodeIdCardNo(fieldValue.toString()));
            }
        }
    }


    @Autowired
    private CommonFeedbackDao commonFeedbackDao;
    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    PlatformTransactionManager platformTransactionManager;
    
    public void encAllTable() {
        String content =
                "soldier_apply_info, , ,resident_address\n" ;
        String[] split = content.split("\n");
        String traceId = MDC.get("traceId");

        CountDownLatch stopLatch = new CountDownLatch(split.length);

        for (String s : split) {
            String[] sp = s.split(",");
            String tableName = sp[0];
            String idCardFieldNamet = sp[1];
            String mobileFieldNamet = sp[2];
            String addressFieldNamet = sp[3];
            if (Strings.isBlank(idCardFieldNamet)) {
                idCardFieldNamet = null;
            }
            if (Strings.isBlank(mobileFieldNamet)) {
                mobileFieldNamet = null;
            }
            if (Strings.isBlank(addressFieldNamet)) {
                addressFieldNamet = null;
            }
            String idCardFieldName = idCardFieldNamet;
            String mobileFieldName = mobileFieldNamet;
            String addressFieldName = addressFieldNamet;

            ThreadPoolManager.getInstance().submit(new Runnable() {
                PlatformTransactionManager tplatformTransactionManager = platformTransactionManager;

                @Override
                public void run() {
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                    TransactionStatus transaction = tplatformTransactionManager.getTransaction(def);
                    MDC.put("traceId", Strings.isBlank(traceId) ? UUID.randomUUID().toString() : traceId);

                    try{
                        
                        
                        if (Strings.isNotBlank(idCardFieldName)) {
                            commonFeedbackDao.alterTable(tableName, idCardFieldName, 60);
                            int loop = 1;
                            List<String> idCardNoList = commonFeedbackDao.groupByField(tableName, idCardFieldName);
                            if (!CollectionUtils.isEmpty(idCardNoList)) {
                                log.info("{}, {}, {}", tableName, idCardFieldName, idCardNoList.size());
                                for (String s : idCardNoList) {
                                    commonFeedbackDao.updateByField(tableName, idCardFieldName, s, PrivacyEncUtils.encodeIdCardNo(s));
                                    log.info("loop:{}, {}, {}", tableName, idCardFieldName, loop++);
                                }
                            }

                        }

                        if (Strings.isNotBlank(mobileFieldName)) {
                            commonFeedbackDao.alterTable(tableName, mobileFieldName, 60);
                            int loop = 1;
                            List<String> idCardNoList = commonFeedbackDao.groupByField(tableName, mobileFieldName);
                            if (!CollectionUtils.isEmpty(idCardNoList)) {
                                log.info("{}, {}, {}", tableName, mobileFieldName, idCardNoList.size());
                                for (String s : idCardNoList) {
                                    commonFeedbackDao.updateByField(tableName, mobileFieldName, s, PrivacyEncUtils.encodeMobile(s));
                                    log.info("loop:{}, {}, {}", tableName, mobileFieldName, loop++);
                                }
                            }
                        }

                        if (Strings.isNotBlank(addressFieldName)) {
                            int loop = 1;
                            List<String> idCardNoList = commonFeedbackDao.groupByField(tableName, addressFieldName);
                            if (!CollectionUtils.isEmpty(idCardNoList)) {
                                log.info("{}, {}, {}", tableName, addressFieldName, idCardNoList.size());
                                for (String s : idCardNoList) {
                                    commonFeedbackDao.updateByField(tableName, addressFieldName, s, PrivacyEncUtils.encodeCommonChinese(s));
                                    log.info("loop:{}, {}, {}", tableName, addressFieldName, loop++);
                                }
                            }
                        }
                        log.info("加密完成：表名：{}", tableName);
                        
                        tplatformTransactionManager.commit(transaction);
                        stopLatch.countDown();
                    }catch(Exception e){
                        
                        log.error("加密的时候发生错误：表名：{}， e:{}", tableName, e);
                        tplatformTransactionManager.rollback(transaction);
                    }
                }
            }
            );
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    stopLatch.await();
                    mybatisCryptAspect.setCrypted(true);
                    SystemConfigDO xitongjiami = systemConfigService.getByName("XITONGJIAMI");
                    BizCheckUtil.checkNotNull(xitongjiami);
                    xitongjiami.setValue("true");
                    systemConfigService.update(xitongjiami);
                } catch (InterruptedException e) {
                    log.error("{}",e);
                }
            }
        }).start();
    }


    public static void main(String[] args) {

    }
}
